package cn.ronghuanet.car.service.impl;

import cn.ronghuanet.base.constants.BaseConstans;
import cn.ronghuanet.base.exception.ResponseCode;
import cn.ronghuanet.base.exception.RonghuaAssert;
import cn.ronghuanet.base.util.BaiduAuditUtil;
import cn.ronghuanet.base.util.VelocityUtils;
import cn.ronghuanet.car.doc.CarDoc;
import cn.ronghuanet.car.domain.Car;
import cn.ronghuanet.car.domain.CarDetail;
import cn.ronghuanet.car.domain.CarOperateLog;
import cn.ronghuanet.car.mapper.CarDetailMapper;
import cn.ronghuanet.car.mapper.CarMapper;
import cn.ronghuanet.car.mapper.CarOperateLogMapper;
import cn.ronghuanet.car.repository.CarDocRepository;
import cn.ronghuanet.car.service.ICarService;
import cn.ronghuanet.base.service.impl.BaseServiceImpl;
import cn.ronghuanet.org.domain.Employee;
import io.swagger.models.auth.In;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author xiong
 * @since 2023-07-03
 */
@Service
public class CarServiceImpl extends BaseServiceImpl<Car> implements ICarService {

    @Autowired
    private CarOperateLogMapper carOperateLogMapper;

    @Autowired
    private CarDetailMapper carDetailMapper;

    @Autowired
    private CarMapper carMapper;

    @Autowired
    private CarDocRepository carDocRepository;

    @Value("${ronghuanet.velocity.templatePath}")
    private String templatePath;

    @Value("${ronghuanet.velocity.targetPath}")
    private String targetPath;

    @Transactional
    @Override
    public void insert(Car car, Employee userInfo) {
        // 1 处理车辆对象
        // 1.1 店铺信息 -> 获取当前登录人所属的店铺信息
        car.setShopId(userInfo.getShop().getId());
        car.setShopname(userInfo.getShop().getName());

        // 1.2 创建时间
        car.setCreatetime(new Date());
        // 1.3 状态=下架
        car.setState(BaseConstans.CarState.CAR_STATE_OFFSALE);

        // 1.4 处理车辆类型
        if(Objects.nonNull(car.getType())){
            car.setTypeId(car.getType().getId());
        }

        // 1.5 销售人员:要不然从前端在新增时选择销售人员, 或者取当前登录人员
        car.setSellerId(userInfo.getId());

        // 2 对车辆信息做审核(标题 基本信息做文本审核  封面做图片审核)
        List<String> texts = Arrays.asList(car.getTitle(),car.getCarDetail().getInfo());
        List<String> imgUrl = Arrays.asList(car.getCover());
        //Map<String, Object> censor = BaiduAuditUtil.censor(texts, imgUrl);
        Map<String, Object> censor = new HashMap<>();
        censor.put("success",true);
        Boolean success = (Boolean)censor.get("success");
        CarOperateLog log = new CarOperateLog();
        if(success){
            // 审核成功,车辆的审核状态=审核通过, 并且操作日志的操作类型=审核通过
            car.setAuditstate(BaseConstans.CarAuditState.CAR_AUDIT_STATE_PASS);

            log.setOperateType(BaseConstans.CarOperateType.CAR_OPERATE_TYPE_AUDIT_PASS);
            log.setNote("系统自动审核通过!");
        }else{
            // 审核失败,车辆的审核状态=审核驳回, 并且操作日志的操作类型=审核驳回
            car.setAuditstate(BaseConstans.CarAuditState.CAR_AUDIT_STATE_REJECT);

            log.setOperateType(BaseConstans.CarOperateType.CAR_OPERATE_TYPE_AUDIT_REJECT);
            log.setNote(censor.get("message").toString());
        }

        // 3 保存车辆信息
        super.insert(car);

        // 4 保存车辆操作日志信息
        log.setCarId(car.getId());
        log.setOperateId(0L);
        log.setOperateTime(new Date());
        carOperateLogMapper.insert(log);

        // 5 保存车辆基本信息到车辆详情表
        CarDetail carDetail = car.getCarDetail();
        carDetail.setCarId(car.getId());
        carDetail.setCartitle(car.getTitle());
        carDetailMapper.insert(carDetail);
    }

    @Transactional
    @Override
    public String onsale(List<Long> ids,Employee userInfo) {
        // 1 参数校验
        // 1.1 判断参数是否为空,如果为空返回错误信息
        RonghuaAssert.isNotNull(ids, ResponseCode.RESPONSE_CODE_40013);

        // 1.2 校验上架的车辆是否满足 审核状态=审核通过并且状态=下架
        // 思考? 如果当前选择了10条数据,其中有1条是审核驳回的,剩下9条是审核成功的,怎么办??
        // 方案一: 只要有一条不满足条件,就返回错误信息,就是一条都不能成功操作 - 只是用户体验度不是很好
        // 方案二: 将审核成功就进行上架,审核驳回就不进行上架,但是要返回当前成功xx条,失败xx条. 甚至可以将失败的车辆标题返回回去 采纳这种
        // 如果车辆状态已经是上架的话,就跳过不处理
        // 1.2.1 根据ids查询到当前做上架操作的所有的车辆信息
        List<Car> cars = carMapper.loadByIds(ids);

        // 1.2.2 筛选审核状态=审核成功并且状态=下架的车辆信息
        cars = cars.stream().filter(x-> x.getAuditstate() == BaseConstans.CarAuditState.CAR_AUDIT_STATE_PASS
                && x.getState() == BaseConstans.CarState.CAR_STATE_OFFSALE).collect(Collectors.toList());

        // 如果当前选择的数据中,没有一条是满足条件的话,就返回错误信息给前端
        RonghuaAssert.isNotNull(cars,ResponseCode.RESPONSE_CODE_40015);

        String msg = "当前操作总条数%s条,成功%s条,失败%s条";
        msg = String.format(msg,ids.size(),cars.size(),ids.size()- cars.size());

        // 2 将满足条件的车辆信息的状态改为上架,并添加上架时间
        ids = cars.stream().map(x -> x.getId()).collect(Collectors.toList());
        carMapper.updateState(ids,BaseConstans.CarState.CAR_STATE_ONSALE);

        // 3 添加操作日志
        saveLog(ids, userInfo,BaseConstans.CarOperateType.CAR_OPERATE_TYPE_ONSALE);

        // 4 添加上架的车辆数据到es中 - 要将当前上架成功的数据添加到es中
        // 将Car重新封装为CarDoc对象,存入es中
        List<CarDoc> docs = getCarDocs(cars);
        carDocRepository.saveAll(docs);

        // 5 给车辆生成静态页面
        for (CarDoc doc : docs) {
            // 每次循环调用工具类生成静态页面
            // 目标路径D:\crm\ronghuanet-car-website\ronghuanet-car-portalsite\carDetails\carId.html
            String path = this.targetPath+"/"+doc.getId()+".html";
            VelocityUtils.staticByTemplate(doc,this.templatePath,path);
        }
        return msg;
    }

    private List<CarDoc> getCarDocs(List<Car> cars) {
        List<CarDoc> docs = new ArrayList<>();
        for (Car car : cars) {
            CarDoc doc = new CarDoc();
            BeanUtils.copyProperties(car,doc);
            // 类型名称
            if(Objects.nonNull(car.getType())){
                doc.setTypeId(car.getType().getId());
                doc.setTypeName(car.getType().getName());
            }

            // 店铺地址
            if(Objects.nonNull(car.getShop())){
                doc.setShopId(car.getShop().getId());
                doc.setShopName(car.getShop().getName());
                doc.setShopAddress(car.getShop().getAddress());
            }

            // 车辆详情
            if(Objects.nonNull(car.getCarDetail())){
                doc.setCarInfo(car.getCarDetail().getInfo());
            }
            docs.add(doc);
        }
        return docs;
    }

    private void saveLog(List<Long> ids, Employee userInfo, Integer type) {
        List<CarOperateLog> logs = new ArrayList<>();
        String note = type == BaseConstans.CarOperateType.CAR_OPERATE_TYPE_ONSALE ? "上架":"下架";
        for (Long id : ids) {
            CarOperateLog log = new CarOperateLog();
            log.setCarId(id);
            log.setOperateType(type);
            log.setOperateId(userInfo.getId());
            log.setOperateTime(new Date());
            log.setNote("车辆id->"+id+note+"成功!");
            logs.add(log);
        }
        carOperateLogMapper.batchInsert(logs);
    }

    @Transactional
    @Override
    public void offsale(List<Long> ids,Employee userInfo) {
        // 1 参数校验
        // 1.1 非空校验
        RonghuaAssert.isNotNull(ids,ResponseCode.RESPONSE_CODE_40014);

        // 2 修改状态=下架,并添加下架时间
        carMapper.updateState(ids,BaseConstans.CarState.CAR_STATE_OFFSALE);

        // 3 添加操作日志
        saveLog(ids, userInfo,BaseConstans.CarOperateType.CAR_OPERATE_TYPE_OFFSALE);

        // 4 删除es中的数据
        for (Long id : ids) {
            carDocRepository.deleteById(id);
        }

        // 5 要删除生成好的静态页面
        for (Long id : ids) {
            String path = this.targetPath+"/"+id+".html";
            File file = new File(path);
            if(file.exists()){
                file.delete();
            }
        }
    }

    @Override
    public void update(Car car) {
        super.update(car);
    }
}
